﻿using System;
using System.Collections.Generic;
using System.Text;

namespace KBEngine.Common
{
    /*
     使用样例：
	var w = KBEngine.Common.Watcher(Define.CELLAPP_TYPE)
	w.connect("127.0.0.1", 12345) // host, port -> got from Machines.ComponentInfo.{intaddr,intport}
	w.requireQueryWatcher("root")
	w.processOne()
	w.watchData
     */
    public class Watcher: ServerApp
    {
        ComponentType _componentType;
        public List<Watch> watchData;
        public Watcher(ComponentType componentType)
        {
            registerMsg(Define.CONSOLE_WATCHERCB_MSGID, onWatcherMsg);
            _componentType = componentType;
            watchData = new List<Watch>();
            System.Diagnostics.Debug.Assert(Array.Exists(Enum.GetNames(typeof(CMD_ID_queryWatcher)), _componentType.ToString().Equals));
        }
        public void clearWatchData()
        {
            watchData.Clear();
        }

        public void requireQueryWatcher(string path)
        {
            var queryWatcherID = (ushort)Enum.Parse(typeof(CMD_ID_queryWatcher), _componentType.ToString());
            Bundle bundle = Bundle.createObject();
            bundle.newMessage(FixedMsg.Get(queryWatcherID));
            bundle.writeString(path);
            send(bundle);
        }

        private void onWatcherMsg(MemoryStream ms)
        {
            var type = ms.readUint8();
            Watch watch = new Watch() { type = type };
            if (type == 0)
            {
                while (!ms.readEOF())
                {
                    var path = ms.readString();
                    var name = ms.readString();
                    var id = ms.readUint16();
                    var wtype = ms.readUint8();
                    var fullpath = path + (path.Length > 0 ? "/" : "") + name;

                    string val = string.Empty;
                    if (wtype == (ushort)WATCHER_VALUE_TYPE.UINT8)
                        val = ms.readUint8().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.UINT16)
                        val = ms.readUint16().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.UINT32)
                        val = ms.readUint32().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.UINT64)
                        val = ms.readUint64().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.UINT8)
                        val = ms.readInt8().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.INT16)
                        val = ms.readInt16().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.INT32)
                        val = ms.readInt32().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.INT64)
                        val = ms.readInt64().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.FLOAT)
                        val = ms.readFloat().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.DOUBLE)
                        val = ms.readDouble().ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.CHAR)
                        val = ms.data()[ms.rpos++].ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.STRING)
                        val = ms.readString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.BOOL)
                        val = (ms.readUint8() == 1).ToString();
                    else if (wtype == (ushort)WATCHER_VALUE_TYPE.COMPONENT_TYPE)
                        val = ms.readInt32().ToString();
                    else
                        System.Diagnostics.Debug.Assert(false, "not support!");

                    watch.path = path;
                    watch.values[name] = val;
                }
            }
            else
            {
                var rootpath = ms.readString();
                if (rootpath == "/")
                    rootpath = string.Empty;

                if (rootpath != null)
                    watch.path = rootpath;

                while (!ms.readEOF())
                { 
                    var path = ms.readString();
                    watch.keys.Add(path);
                }
            }
            watchData.Add(watch);
        }

        public class Watch
        {
            public byte type;
            public string path = string.Empty;
            public Dictionary<string, string> values = new Dictionary<string, string>();
            public List<string> keys = new List<string>();
        }

        private enum CMD_ID_queryWatcher: ushort
        {
            baseapp    = 41001,
            cellapp    = 41002,
            loginapp   = 41003,
            baseappmgr = 41004,
            cellappmgr = 41005,
            dbmgr      = 41006,
            interfaces = 41007,
            logger     = 41008,
        }

        /// <summary>
        /// watcher数据类型定义
        /// </summary>
        private enum WATCHER_VALUE_TYPE: ushort
        {
            UNKNOWN = 0,
            UINT8 = 1,
            UINT16 = 2,
            UINT32 = 3,
            UINT64 = 4,
            INT8 = 5,
            INT16 = 6,
            INT32 = 7,
            INT64 = 8,
            FLOAT = 9,
            DOUBLE = 10,
            CHAR = 11,
            STRING = 12,
            BOOL = 13,
            COMPONENT_TYPE = 14,
        }
    }
}
